from jili.core.printlog import print
import pandas as pd
import pyfinance as pf
from jili.data.db import getdb_client, insert_one,get_calender
import datetime,os
"""
暂时搁置 库内保存
但是要保证净值返回形成一定的内容
后续增加内容：
1.指定手数与总资金
2.计算仓位与空仓期

持仓类型：
单合约  占比持仓
多合约占比合约
多合约  占比持仓

1.大批量回测  不关心亏损情况，不盈利的不放算例计算过多指标；亏货不值得计算，赚钱的也不要保存net,是否计算多周期收益
2.单个执行，看详细,
3.保存net,orders
"""
cu=None
cu_net=None
cu_signal=None
def rrf(d):
    if d.empty:
        return 0
    d=d+1
    d=d.cumprod()
    r=d.tolist()[-1]-1
    return r
def deal_nan2none(d):
    rst={}
    for k,v in d.items():
        if isinstance(v,dict):
            rst[k]=deal_nan2none(v)
        elif isinstance(v,list) or isinstance(v,tuple):
            t=[]
            for i in v:
                if pd.isna(i):
                    t.append(None)
                else:
                    t.append(i)
            rst[k]=t
        else:
            if pd.isna(v):
                rst[k]=None
            else:
                rst[k]=v
    return rst

def get_rrs(rr,flag,isdetail=0):
    rst={}
    t=rr.resample(flag).apply(rrf)
    if len(t)==0:
        r0=0
        r1=0
    else:
        r0=round(100*len(t[t>0])/len(t),2)
        r1=round(100*len(t[t<0])/len(t),2)
    if len(t[t!=0])==0:
        r2=0
    else:
        r2= round(100*len(t[t > 0]) / len(t[t!=0]), 2)
    if isdetail==2:
        t=t.to_dict()
        for k,v in t.items():
            key=k.to_pydatetime()
            rst[key]=float(v)
    return rst,(r0,r1,r2)

def performance_net(plr_d,start_date=None,end_date=None,isdetail=0,pos_rate={}):
    nets = {}
    rst={}
    if start_date   is None:
        ds = list(plr_d.keys())
        ds.sort()
        start_date = ds[0]
        if len(ds) == 1:
            end_date = ds[0]
        else:
            end_date = ds[1]
    if pos_rate:
        maxposrate=max(list(pos_rate.values()))
        rst["最大仓位"]=maxposrate
    nopos = 0
    for d in get_calender(start_date, end_date):
        if d not in plr_d.keys():
            plr_d[d] = 0
            nopos = nopos + 1
        elif d in pos_rate.keys():
            if pos_rate[d]<=0.01:
                nopos = nopos + 1
    rst["无机会占比(%)"] = float(round(100 * nopos / len(plr_d), 1))
    rst["策略占用(%)"] = float(round(100 - rst["无机会占比(%)"], 1))
    rrr = pd.Series(plr_d)
    rrr.sort_index(inplace=True)
    r_w, r_w_r = get_rrs(rrr, "1W", isdetail)
    r_m, r_m_r = get_rrs(rrr, "1M", isdetail)
    r_q, r_q_r = get_rrs(rrr, "1Q", isdetail)
    r_a, r_a_r = get_rrs(rrr, "1A", isdetail)
    if len(rrr)==0:
        rst["日赢占比(%)"] =0
    else:
        rst["日赢占比(%)"] = round(100*len(rrr[rrr > 0]) / len(rrr), 2)
    rst["周赢占比(%)"] = r_w_r[0]
    rst["月赢占比(%)"] = r_m_r[0]
    rst["季赢占比(%)"] = r_q_r[0]
    rst["年赢占比(%)"] = r_a_r[0]
    if len(rrr)==0:
        rst["日亏占比(%)"] =0
    else:
        rst["日亏占比(%)"] = round(100*len(rrr[rrr < 0]) / len(rrr), 2)
    rst["周亏占比(%)"] = r_w_r[1]
    rst["月亏占比(%)"] = r_m_r[1]
    rst["季亏占比(%)"] = r_q_r[1]
    rst["年亏占比(%)"] = r_a_r[1]
    if len(rrr[rrr != 0])==0:
        rst["日赢亏占比(%)"] =0
    else:
        rst["日赢亏占比(%)"] = round(100*len(rrr[rrr > 0]) / len(rrr[rrr != 0]), 2)
    rst["周赢亏占比(%)"] = r_w_r[2]
    rst["月赢亏占比(%)"] = r_m_r[2]
    rst["季赢亏占比(%)"] = r_q_r[2]
    rst["年赢亏占比(%)"] = r_a_r[2]

    rr = pf.TSeries(rrr)
    # rr.sort_index(inplace=True)
    rr.freq = "D"
    rst["年化收益(%)"] = float(round(rr.anlzd_ret() * 100, 2))
    rst["累计收益率"]=rr.cuml_ret()
    rst["总收益(%)"] = float(round(rst["累计收益率"] * 100, 2))
    rst["向上比率(%)"] = float(round(rr.pct_positive()* 100, 2))
    rst["向下比率(%)"] = float(round(rr.pct_negative()* 100, 2))
    #下行标准差
    rst['下行标准差']=round(rr.semi_stdev(),5)
    try:
        rst["年化标准差"] = rr.anlzd_stdev()
        rst["夏普值"] = rr.sharpe_ratio()
    except Exception as e:
        rst["年化标准差"] = 0
        rst["夏普值"] = 10000
    max_draw = rr.max_drawdown()
    if max_draw == 0.0:
        rst["卡玛比率"] = 10000
        rst["最大回撤(%)"] = float(round(max_draw * 100, 2))
    else:
        rst["卡玛比率"] = rr.calmar_ratio()
        rst["最大回撤(%)"] = float(round(max_draw * 100, 2))
    rst["回撤积分"] = rr.drawdown_idx().abs().sum()
    max_draw = float(rr.max_drawdown())
    rst["最深回撤(%)"] = float(round(max_draw*100, 2))
    if max_draw == 0.0:
        rst["最深回撤(天)"] = None
        rst["最深回撤日"] = None
        rst["最深回撤开始"] = None
        rst["最深回撤结束"] = None
        rst["最长回撤(%)"] = 0
        rst["最长回撤(天)"] = 0
        rst["最长回撤日"] = 0
        rst["最长回撤开始"] = None
        rst["最长回撤结束"] = None
        rst["卡玛比率"] = None
        rst["索提诺比率"] = None
        rst["痛苦指数"] = None
    else:
        drawdown = rr.drawdown_idx()
        drawdownd0 = pd.DataFrame(drawdown)
        drawdownd0.columns = ["drawdown"]
        max_draw_date = drawdownd0.loc[drawdownd0["drawdown"] == max_draw].index.to_list()[0]
        drawdownd0.iloc[0, -1] = 0
        drawdownd0.iloc[-1, -1] = 0
        # drawdownd.drop_duplicates(subset=["drawdown"],inplace=True)
        # drawdownd0.loc[:,"d"]=drawdownd0.index
        drawdownd0["d"] = drawdownd0.index
        drawdownd = drawdownd0.loc[drawdownd0["drawdown"] >= 0].copy()
        prei = None
        for i in drawdownd["d"].to_list():
            if prei:
                if prei < max_draw_date and i >= max_draw_date:
                    d0 = i - prei
                    rst["最深回撤(天)"] = d0.days
                    rst["最深回撤日"] = max_draw_date.to_pydatetime()
                    rst["最深回撤开始"] = prei.to_pydatetime()
                    rst["最深回撤结束"] = i.to_pydatetime()
                    break
            prei = i
        # drawdownd.loc[:,"d1"]=drawdownd["d"].diff()
        drawdownd["d1"] = drawdownd["d"].diff()
        macdays = drawdownd["d1"].max()
        dd = drawdownd.loc[drawdownd["d1"] == macdays]["d"].to_list()[0]
        dd = dd.to_pydatetime()
        dd0 = dd - datetime.timedelta(days=macdays.days)
        drawdownd1 = drawdownd0.loc[(drawdownd0["d"] >= dd0) & (drawdownd0["d"] <= dd)]
        min0 = drawdownd1["drawdown"].min()

        rst["最长回撤(%)"] = round(100*min0,2)
        rst["最长回撤(天)"] = macdays.days
        rst["最长回撤日"] = drawdownd1.loc[drawdownd1["drawdown"] == min0]["d"].to_list()[0].to_pydatetime()
        rst["最长回撤期开始"] = dd0
        rst["最长回撤期结束"] = dd
        rst["卡玛比率"] = float(round(rr.calmar_ratio(), 2))
        dd = rr.sortino_ratio(freq=250)
        rst["索提诺比率"] = float(round(dd, 2))

        drawdownd0.loc[drawdownd0["drawdown"] > -0.01, "drawdown"] = 0
        drawdownd = drawdownd0.loc[drawdownd0["drawdown"] >= 0].copy()
        prei = None
        days0 = 0
        total_days = drawdownd0.iloc[-1, -1] - drawdownd0.iloc[0, -1]
        for i in drawdownd["d"].to_list():
            if prei:
                if prei < max_draw_date and i >= max_draw_date:
                    d0 = i - prei
                    days0 = days0 + d0.days
            prei = i
        rst["痛苦指数"] = days0 / total_days.days

    net = rrr + 1
    net = net.cumprod()

    if isdetail == 2:
        nets["周收益"] = r_w
        nets["月收益"] = r_m
        nets["季收益"] = r_q
        nets["年收益"] = r_a
        td = pd.concat([rrr, net], axis=1, ignore_index=True)
        td.columns = ["r", "net"]
        t = td.to_dict("index")
        td = {}
        for k, v in t.items():
            key = k.to_pydatetime()
            td[key] = v
        nets["net"] = td
        nets["return"]=plr_d
        nets["drawdown"]=drawdown
    return rst,nets

